#ifndef _CPLAYER_H
#define _CPLAYER_H

class CPlayer
{
public:
	CPlayer(byte* basePtr)
	{
		mptr = basePtr;
	}
	~CPlayer() { }

	void SetBasePtr(byte* basePtr)
	{
		mptr = basePtr;
	}

	byte* GetBasePtr() { return mptr; }

	float GetX() { return TryRead<float>(0xA8); }
	float GetY() { return TryRead<float>(0xAC); }
	bool GetIsMounted() { return TryRead<bool>(0x17C); }
	long GetUniqueId() { return TryRead<long>(0x294); }
	unsigned long GetProfession() { return TryRead<unsigned long>(0x3E0); }
	bool GetIsMoving() { return TryRead<bool>(0x96C); }
	bool GetHavePet() { return TryRead<bool>(0xB2C); }
	unsigned long GetPetId() { return TryRead<unsigned long>(0xB30); }
	unsigned long GetMasterId() { return TryRead<unsigned long>(0xB3C); }
	unsigned long GetCurrentHp() { return TryRead<unsigned long>(0x143C); }
	unsigned long GetMaxHp() { return TryRead<unsigned long>(0x1440); }
	unsigned long GetCurrentMp() { return TryRead<unsigned long>(0x1444); }
	unsigned long GetMaxMp() { return TryRead<unsigned long>(0x1448); }
	unsigned long GetCurrentRage() { return TryRead<unsigned long>(0x144C); }
	unsigned long GetMaxRage() { return TryRead<unsigned long>(0x1450); }
	bool GetIsDead() { return (TryRead<byte>(0x14A1) == 1); }
	unsigned char GetPlayerType() { return TryRead<unsigned char>(0x14F8); }
	unsigned long GetLevel() { return TryRead<unsigned long>(0x5B34); }
	float GetSpeed() { return TryRead<float>(0x5B18); }

	bool SetSpeed(float value) { return TryWrite<float>(0x5B18, value); }

	char* GetName()
	{
		if(TryRead<unsigned long>(0x2BC) == 0xF)
			return (char*)(mptr + 0x2A8);
		else if(TryRead<unsigned long>(0x2BC) == 0x1F)
			return TryRead<char*>(0x2A8);
		return NULL;
	}

	void TurnToPlayer(byte* player)
	{
		byte* TurnToPlayerFunctionPtr = Mem->GetAddress("TurnToPlayerFunction");
		if(!TurnToPlayerFunctionPtr)
			return;

		_asm {
			PUSH player
			MOV ECX,mptr
			CALL TurnToPlayerFunctionPtr
		}
	}

	float GetDistanceToPlayer(CPlayer* player)
	{
		return sqrt(pow(this->GetX() - player->GetX(), 2) + pow(this->GetY() - player->GetY(), 2));
	}

	void TryTalkWithNpc(long playerId)
	{
		byte* TryTalkWithNpcFunctionPtr = Mem->GetAddress("TryTalkWithNpcFunction");
		CPlayer* npc = CPlayerMgr::FindPlayerById(playerId);
	
		if(!TryTalkWithNpcFunctionPtr || !npc)
			return;

		byte* playerPtr = npc->GetBasePtr();
		delete npc;

		_asm {
			PUSH playerPtr
			MOV ECX,mptr
			CALL TryTalkWithNpcFunctionPtr
		}
	}

private:
	template <typename T> T TryRead(unsigned long offset)
	{
		__try {
			return *(T*)(mptr + offset);
		}
		__except (1) {
			return (T)NULL;
		}
	}

	template <typename T> bool TryWrite(unsigned long offset, T value)
	{
		__try {
			*(T*)(mptr + offset) = value;
			return true;
		}
		__except(1) {
			return false;
		}
	}

	byte* mptr;
};

#endif